#include <node.h>
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
#include <sstream>

#include <node.h>
#include <v8.h>

using namespace v8;
using namespace std;

namespace nxmi {

  using v8::Local;
  using v8::Object;
  void Methodone(const FunctionCallbackInfo<Value>& args) {
    // printf(& args);
    Isolate* isolate = Isolate::GetCurrent();
    HandleScope scope(isolate);
    Local<String> retval = String::NewFromUtf8(isolate, "zhanga234",v8::NewStringType::kInternalized).ToLocalChecked();
    args.GetReturnValue().Set(retval);
    //args.GetReturnValue().Set(String::NewFromUtf8(isolate, "method one helloxxx"));
  }

  void Invoke(const FunctionCallbackInfo<Value>& args){
     //printf("start call Invoke\n");
      Isolate* isolate = Isolate::GetCurrent();
      HandleScope scope(isolate);
      //v8::String::Utf8Value data(args[0]->ToString());

      v8::String::Utf8Value data(v8::Isolate::GetCurrent(), args[0]);

      std::string returnValue = std::string(*data);
      // printf("%s\n",returnValue.c_str());
      ::HINSTANCE hDLL = NULL;
      // printf("start call dll \n");

      typedef void ( __stdcall *node_invoke)(char*,char**);

      char* pBuf = new char[2048];
      memset(pBuf, 0, 2048);
      // char[] indataaaa =returnValue ;
      char* indata  = (char*) returnValue.c_str() ;

      // procedure nodeaddon_invoke(params : PChar;var result : PChar) ; stdcall ;
      // typedef char*(*pHDSerialNumRead)(string,string,string,string);
      hDLL = LoadLibrary("nxmi.dll");

      if(hDLL){
          // printf("dll Exists\n");
          node_invoke finvoke=(node_invoke)GetProcAddress(hDLL,"nodeaddon_invoke");
          if (finvoke){
              // printf("%s", indata);
              // printf("111111111111111111111111 \n");
              try{
                 char* _result= (char*)malloc(2408);
                 finvoke(indata,&_result);
                 returnValue = _result ;
                 free(_result);
              }catch(exception e){
                DWORD err = GetLastError();
                printf("%u", err);
                //printf("xxxx0");
                Local<String> retval = String::NewFromUtf8(isolate, "method invoke not Exists",v8::NewStringType::kInternalized).ToLocalChecked();
                isolate->ThrowException(Exception::TypeError(retval));
              }
          }else{
              //DWORD err = GetLastError();
              //std::string returnValue = std::string(err);
              // printf("%u", err);
              //printf("xxxx01");
              //isolate->ThrowException(Exception::TypeError(
              //                   String::NewFromUtf8(isolate, "method invoke not Exists")));
          };
      }else{
          //DWORD err = GetLastError();
          //std::string returnValue = std::string(err);
          //printf("%u", err);
          //printf("xxxx00");
          //isolate->ThrowException(Exception::TypeError(
          //          String::NewFromUtf8(isolate, "nxmi.DLL not Exists")));
      };
      FreeLibrary(hDLL) ;
      //args.GetReturnValue().Set(String::NewFromUtf8(isolate, returnValue.c_str()));

      Local<String> retval = String::NewFromUtf8(isolate, returnValue.c_str(),v8::NewStringType::kInternalized).ToLocalChecked();
      args.GetReturnValue().Set(retval);

    }



  //void init(Handle<Object> exports) {
    void init(Local<Object> exports){
    // printf("Hello node & V8 \n");
    NODE_SET_METHOD(exports, "hello", Methodone);
    NODE_SET_METHOD(exports, "invoke", Invoke);
  }


  void hello() {
    printf("Hello node & V8 \n");
  }

  NODE_MODULE(nxmi, init)
}